package com.example.origin.mysql.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.example.origin.mysql.domain.User;
import com.example.origin.mysql.service.UserService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.bind.annotation.RequestParam;

import javax.sql.DataSource;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
@EnableTransactionManagement
public class UserServiceImpl implements UserService {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private PlatformTransactionManager platformTransactionManager;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Qualifier("dataSource")
    @Autowired
    private DataSource dataSource;
    static final String sql = "INSERT INTO user(name,age) VALUES(?,?)";
    static final String query = "SELECT id,name,age FROM user WHERE id= ?";

    @Override
    public boolean save(User user) {
        return Boolean.TRUE.equals(transactionTemplate.execute(action -> addUser(user)));
    }

    private Boolean addUser(User user) {
        return jdbcTemplate.execute(sql, (PreparedStatementCallback<Boolean>) ps -> {
            ps.setString(1, user.getName());
            ps.setInt(2, user.getAge());
            return ps.executeUpdate() > 0;
        });
    }

    public boolean save2(User user) {
        boolean result = false;
        DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
        TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
        try {
            result = addUser(user);
            platformTransactionManager.commit(transactionStatus);
        } catch (Exception e) {
            platformTransactionManager.rollback(transactionStatus);
        }
        return result;
    }

    @SneakyThrows
    public User getUser(int id) {
        Map<String, Object> data = new HashMap<String, Object>();
        Connection connection = null;
        Savepoint savepoint = null;
        try {
            connection = dataSource.getConnection();
            connection.setAutoCommit(false);
            savepoint = connection.setSavepoint();

            PreparedStatement statement = connection.prepareStatement(query);
            statement.setInt(1, id);
            ResultSet resultSet = statement.executeQuery();
            while (resultSet.next()) {
                int id_ = resultSet.getInt("id");
                String name = resultSet.getString("name");
                int age = resultSet.getInt("age");
                data.put("id", id_);
                data.put("name", name);
                data.put("age", age);
            }
            connection.commit();
            return BeanUtil.toBean(data, User.class);
        } catch (SQLException e) {
            if (connection != null) {
                try {
                    connection.rollback(savepoint);
                } catch (SQLException e1) {
                    log.error("error", e1);
                }
            }
            log.error("error", e);
            throw e;
        } finally {
            try {
                if (connection != null) {
                    connection.setAutoCommit(true);
                    connection.close();
                }
            } catch (SQLException e) {
                log.error("error", e);
            }
        }
    }
}